/* Copyright Statement:
 *
 * This software/firmware and related documentation ("AutoChips Software") are
 * protected under relevant copyright laws. The information contained herein is
 * confidential and proprietary to AutoChips Inc. and/or its licensors. Without
 * the prior written permission of AutoChips inc. and/or its licensors, any
 * reproduction, modification, use or disclosure of AutoChips Software, and
 * information contained herein, in whole or in part, shall be strictly
 * prohibited.
 *
 * AutoChips Inc. (C) 2023. All rights reserved.
 *
 * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
 * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("AUTOCHIPS SOFTWARE")
 * RECEIVED FROM AUTOCHIPS AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
 * ON AN "AS-IS" BASIS ONLY. AUTOCHIPS EXPRESSLY DISCLAIMS ANY AND ALL
 * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
 * NONINFRINGEMENT. NEITHER DOES AUTOCHIPS PROVIDE ANY WARRANTY WHATSOEVER WITH
 * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
 * INCORPORATED IN, OR SUPPLIED WITH THE AUTOCHIPS SOFTWARE, AND RECEIVER AGREES
 * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
 * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
 * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN AUTOCHIPS
 * SOFTWARE. AUTOCHIPS SHALL ALSO NOT BE RESPONSIBLE FOR ANY AUTOCHIPS SOFTWARE
 * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
 * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND AUTOCHIPS'S
 * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE AUTOCHIPS SOFTWARE
 * RELEASED HEREUNDER WILL BE, AT AUTOCHIPS'S OPTION, TO REVISE OR REPLACE THE
 * AUTOCHIPS SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
 * CHARGE PAID BY RECEIVER TO AUTOCHIPS FOR SUCH AUTOCHIPS SOFTWARE AT ISSUE.
 */

/*!
 * @file ac780x_i2c.h
 *
 * @brief This file provides i2c integration functions interface.
 *
 */

#ifndef _AC780X_I2C_H
#define _AC780X_I2C_H

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

/* ============================================  Includes  ============================================ */
#include "ac7803x.h"

/* ============================================  Define  ============================================ */
#define I2C_USE_INTERRUPT_TRANSMIT

/*!
 * @brief I2C 10bit address reserve mask bit macro.
 */
#define I2C_ADDEXT_PRIMARY_BYTE_FIX 0xF8UL

/*!
 * @brief I2C hardware timeout count macro.
 */
#define I2C_HW_DEADLINE_TIMEOUT 0x80000UL

/*!
 * @brief I2C instance index macro.
 */
#define I2C_INDEX(I2Cx)    ((uint8_t)(((uint32_t)(I2Cx) - I2C0_BASE) >> 12U))

/*!
 * @brief I2C hardware status macro.
 */
#define I2C_HW_STATUS_ERROR_NULL            0x00UL        /*!< I2C hardware status : without error */
#define I2C_HW_STATUS_BUS_BUSY              0x01UL        /*!< I2C hardware status : bus busy */
#define I2C_HW_STATUS_NACK                  0x02UL        /*!< I2C hardware status : get nack */
#define I2C_HW_STATUS_BND_TIMEOUT           0x04UL        /*!< I2C hardware status : one byte transfer timeout error */
#define I2C_HW_STATUS_CORE_READY_TIMROUT    0x08UL        /*!< I2C hardware status : wait ready timeout error */
#define I2C_HW_STATUS_START_TO_BUSY_TIMEOUT 0x10UL        /*!< I2C hardware status : send start to busy timeout error */
#define I2C_HW_STATUS_STOP_TO_IDLE_TIMEOUT  0x20UL        /*!< I2C hardware status : send stop to idle timeout error */

/*!
 * @brief I2C application status macro.
 */
#define I2C_TRANSMIT_STATUS_ERROR_NULL      0x00UL        /*!< I2C transmit status : without error */
#define I2C_TRANSMIT_STATUS_NOT_MATCH       0x01UL        /*!< I2C transmit status : master addressing slave not match */
#define I2C_TRANSMIT_STATUS_MATCHED         0x02UL        /*!< I2C transmit status : slave get matched */
#define I2C_TRANSMIT_STATUS_NACK            0x04UL        /*!< I2C transmit status : get nack */
#define I2C_TRANSMIT_STATUS_FINISHED        0x08UL        /*!< I2C transmit status : TX/RX transmit finished */
#define I2C_TRANSMIT_STATUS_TXUF            0x10UL        /*!< I2C transmit status : slave TX under flow */
#define I2C_TRANSMIT_STATUS_RXOF            0x20UL        /*!< I2C transmit status : slave RX over flow */
#define I2C_TRANSMIT_STATUS_ARBLOST         0x40UL        /*!< I2C transmit status : arbitration lost */
#define I2C_TRANSMIT_STATUS_START_FLAG      0x100UL       /*!< I2C transmit status : get start flag */
#define I2C_TRANSMIT_STATUS_STOP_FLAG       0x200UL       /*!< I2C transmit status : get stop flag */

/* ===========================================  Typedef  ============================================ */
/*!
 * @brief I2C write/read enum.
 */
typedef enum
{
    I2C_WRITE = 0x00U,      /*!< I2C write transfer */
    I2C_READ  = 0x01U       /*!< I2C read transfer */
} I2C_WRType;

/*!
 * @brief I2C ack/nack enum.
 */
typedef enum
{
    I2C_ACK  = 0x00U,       /*!< I2C send ack on next byte */
    I2C_NACK = 0x01U        /*!< I2C send nack on next byte */
} I2C_AckType;

/*!
 * @brief I2C master/slave mode enum.
 */
typedef enum
{
    I2C_SLAVE  = 0x00U,     /*!< I2C slave mode */
    I2C_MASTER = 0x01U      /*!< I2C master mode */
} I2C_ModeType;

/*!
 * @brief I2C configuration structure for master attribute.
 *
 * This structure holds the configuration settings for the I2C master attribute
 */
typedef struct
{
    uint8_t sampleCnt;      /*!< I2C sample cnt */
    uint8_t stepCnt;        /*!< I2C step cnt */
    ACTION_Type SYNCEn;     /*!< Enable/disable SCL SYNC */
    ACTION_Type ARBEn;      /*!< Enable/disable Arbitration */
} I2C_MasterConfigType;

/*!
 * @brief I2C configuration structure for slave attribute.
 *
 * This structure holds the configuration settings for the I2C slave attribute
 */
typedef struct
{
    uint16_t slaveAddr;                 /*!< slave 7/10bit address value */
    uint8_t slaveRangeAddr;             /*!< slave 7bit range address value */
    uint8_t glitchFilterCnt;            /*!< i2c glitch filter cnt */
    ACTION_Type stretchEn;              /*!< Enable/disable slave SCL stretch */
    ACTION_Type txUFInterruptEn;        /*!< Enable/disable slave Tx buff under flow interrupt */
    ACTION_Type rxOFInterruptEn;        /*!< Enable/disable slave Rx buff over flow interrupt */
    ACTION_Type rangeAddrEn;            /*!< Enable/disable slave 7bit range address */
    ACTION_Type monitorEn;              /*!< Enable/disable slave monitor */
    ACTION_Type generalCallEn;          /*!< Enable/disable slave general call */
    ACTION_Type wakeupEn;               /*!< Enable/disable slave address match wakeup */
} I2C_SlaveConfigType;

/*!
 * @brief I2C configuration structure.
 *
 * This structure holds the configuration settings for the I2C
 */
typedef struct
{
    I2C_ModeType mode;                  /*!< Select i2c module mode */
    ACTION_Type extAddrEn;              /*!< Enable/disable master/slave 10bit address */
    ACTION_Type ssInterruptEn;          /*!< Enable/disable detect start/stop interrupt */
    ACTION_Type nackInterruptEn;        /*!< Enable/disable get nack interrupt */
    ACTION_Type interruptEn;            /*!< Enable/disable i2c global interrupt */
    ACTION_Type dmaTxEn;                /*!< Enable/disable DMA transmit */
    ACTION_Type dmaRxEn;                /*!< Enable/disable DMA receive */
    ACTION_Type i2cEn;                  /*!< Enable/disable i2c module */
    I2C_MasterConfigType masterConfig;  /*!< i2c master config types */
    I2C_SlaveConfigType slaveConfig;    /*!< i2c slave config types */
    DeviceCallback_Type callBack;       /*!< i2c call back function */
} I2C_ConfigType;

/*!
 * @brief I2C master/slave write/read info structure.
 *
 * This structure holds the user configuration info
 */
typedef struct
{
    uint32_t pointer;       /*!< position of send data in user defined buffer */
    uint32_t length;        /*!< length of user defined to write/read */
    uint8_t *buff;          /*!< pointer to user defined buffer */
    I2C_WRType wr;          /*!< i2c transmit type, Master only  */
    ACTION_Type stopEn;     /*!< enable i2c send stop after lastone byte, Master only */
} I2C_TransmitType;

/*!
 * @brief I2C instance structure.
 *
 * This structure holds the i2c clock and reset configuration info
 */
typedef struct
{
    I2C_Type *I2Cx;                 /*!< I2C instance: I2C0, I2C1 */
    IRQn_Type I2Cx_IRQn;            /*!< I2C interrupt vector: I2C0_IRQn, I2C1_IRQn */
    CKGEN_ClockType CKGEN_I2Cx;     /*!< I2C module clock: CKGEN_I2C0, CKGEN_I2C1 */
    CKGEN_SoftResetType SRST_I2Cx;  /*!< I2C module reset: SRST_I2C0, SRST_I2C1 */
} I2C_INFOType;

/* ==========================================  Variables  =========================================== */

/* ====================================  Functions declaration  ===================================== */
/*!
 * @brief Initialize I2C module.
 *
 * @param[in] I2Cx: i2c module,x can be 0.1
 * @param[in] config: I2C configuration pointer
 * @return none
 */
void I2C_Init(I2C_Type *I2Cx, const I2C_ConfigType *config);

/*!
 * @brief I2C De-initialize.
 *
 * @param[in] I2Cx: i2c module,x can be 0.1
 * @return none
 */
void I2C_DeInit(I2C_Type *I2Cx);

/*!
 * @brief set I2C Callback function.
 *
 * @param[in] I2Cx: i2c module,x can be 0.1
 * @param[in] callback: call back function
 * @return none
 */
void I2C_SetCallback(I2C_Type *I2Cx, DeviceCallback_Type callback);

/*!
 * @brief I2C send start.
 *
 * @param[in] I2Cx: I2C module,x can be 0.1
 * @return i2c hardware status
 */
uint32_t I2C_Start(I2C_Type *I2Cx);

/*!
 * @brief I2C send re-start,make sure to disable start/stop interrupt when use the interface.
 *
 * @param[in] I2Cx: I2C module,x can be 0.1
 * @return i2c hardware status
 */
uint32_t I2C_Restart(I2C_Type *I2Cx);

/*!
 * @brief I2C send stop
 *
 * @param[in] I2Cx: I2C module,x can be 0.1
 * @return i2c hardware status
 */
uint32_t I2C_Stop(I2C_Type *I2Cx);

/*!
 * @brief wait one byte transmit finished.
 *        if use Master DMA transmit, user must call this API when DMA transmit finished, then user decided to send stop
 *        if use Slave DMA transmit, it's recommended that the user call this API to clear some status
 *
 * @param[in] I2Cx: I2C module,x can be 0.1
 * @return i2c hardware status
 */
uint32_t I2C_WaitOneByteFinished(I2C_Type *I2Cx);

/*!
 * @brief I2C write one byte with polling BND flag,make sure to disable interrupt when use the interface.
 *
 * @param[in] I2Cx: I2C module,x can be 0.1
 * @param[in] data: data to write
 * @return i2c hardware status
 */
uint32_t I2C_TransmitOneByte(I2C_Type *I2Cx, uint8_t data);

/*!
 * @brief I2C read one byte and send next clock,make sure to disable interrupt when use the interface.
 *
 * @param[in] I2Cx: I2C module,x can be 0.1
 * @param[in] data: data to read
 * @param[in] nack: the next byte ack status
 * @return i2c hardware status
 */
uint32_t I2C_ReceiveOneByte(I2C_Type *I2Cx, uint8_t *data, I2C_AckType nack);

/*!
 * @brief I2C read one byte without send next clock.
 *
 * @param[in] I2Cx: I2C module,x can be 0.1
 * @param[in] data: data to read
 * @return none
 */
void I2C_ReceiveLastOneByte(I2C_Type *I2Cx, uint8_t *data);

/*!
 * @brief I2C get internal hardware ready status.
 *
 * @param[in] I2Cx: I2C module,x can be 0.1
 * @return i2c hardware status
 */
uint32_t I2C_WaitForReady(I2C_Type *I2Cx);

/*!
 * @brief I2C burst write with 7bit/10bit addressing,make sure to disable interrupt when use the interface.
 *
 * @param[in] I2Cx: I2C module,x can be 0.1
 * @param[in] slaveAddr: slave 7bit/10bit address
 * @param[in] buff: the data buffer
 * @param[in] dataLength: the length to write
 * @param[in] stopEn: enable/diable i2c send stop after lastone byte for a possible re-start
 * @return i2c hardware status
 */
uint32_t I2C_MasterTransmitPoll(I2C_Type *I2Cx, uint16_t slaveAddr, uint8_t *buff, uint32_t dataLength, ACTION_Type stopEn);

/*!
 * @brief I2C burst read with 7bit/10bit addressing,make sure to disable interrupt when use the interface.
 *
 * @param[in] I2Cx: I2C module,x can be 0.1
 * @param[in] slaveAddr: slave 7bit/10bit address
 * @param[in] buff: the data buffer
 * @param[in] dataLength: the length to read
 * @return i2c hardware status
 */
uint32_t I2C_MasterReceivePoll(I2C_Type *I2Cx, uint16_t slaveAddr, uint8_t *buff, uint32_t dataLength);

/*!
 * @brief I2C master start DMA transmit.
 *        this will initialize DMA channel with the general DMA config
 *        make sure to enable i2c dma tx in I2C_Init before use the interface
 *        master start DMA transmit only when slave address match
 *        master get slave address or data nack need enable nack interrupt first
 *
 * @param[in] I2Cx: I2C module,x can be 0.1
 * @param[in] slaveAddr: 7/10bit slave address
 * @param[in] DMAx: DMA module
 * @param[in] txBuffer: memory start address
 * @param[in] length: length to transmit
 * @param[in] callback: the DMA interrupt callback function
 * @return i2c hardware status
 */
uint32_t I2C_MasterTransmitDMA(I2C_Type *I2Cx, uint16_t slaveAddr, DMA_ChannelType *DMAx, uint8_t *txBuffer, uint16_t length, DeviceCallback_Type callback);

/*!
 * @brief I2C master start DMA receive.
 *        this will initialize DMA channel with the general DMA config
 *        make sure to enable i2c dma rx in I2C_Init before use the interface
 *        master start DMA receive only when slave address match
 *        master get slave address nack need enable nack interrupt first
 *        DMA receive length must > 1
 *
 * @param[in] I2Cx: I2C module,x can be 0.1
 * @param[in] slaveAddr: 7/10bit slave address
 * @param[in] DMAx: DMA module
 * @param[in] rxBuffer: memory start address
 * @param[in] length: length to receive
 * @param[in] callback: the DMA interrupt callback function
 * @return i2c hardware status
 */
uint32_t I2C_MasterReceiveDMA(I2C_Type *I2Cx, uint16_t slaveAddr, DMA_ChannelType *DMAx, uint8_t *rxBuffer, uint16_t length, DeviceCallback_Type callback);

/*!
 * @brief I2C slave start DMA transmit.
 *        this will initialize DMA channel with the general DMA config
 *        make sure to enable i2c dma tx in I2C_Init before use the interface
 *        slave start DMA transmit only when slave address match
 *
 * @param[in] I2Cx: I2C module,x can be 0.1
 * @param[in] DMAx: DMA module
 * @param[in] txBuffer: memory start address
 * @param[in] length: length to transmit
 * @param[in] callback: the DMA interrupt callback function
 * @return none
 */
void I2C_SlaveTransmitDMA(I2C_Type *I2Cx, DMA_ChannelType *DMAx, uint8_t *txBuffer, uint16_t length, DeviceCallback_Type callback);

/*!
 * @brief I2C slave start DMA receive.
 *        this will initialize DMA channel with the general DMA config
 *        make sure to enable i2c dma rx in I2C_Init before use the interface
 *        slave start DMA receive only when slave address match
 *
 * @param[in] I2Cx: I2C module,x can be 0.1
 * @param[in] DMAx: DMA module
 * @param[in] rxBuffer: memory start address
 * @param[in] length: length to receive
 * @param[in] callback: the DMA interrupt callback function
 * @return none
 */
void I2C_SlaveReceiveDMA(I2C_Type *I2Cx, DMA_ChannelType *DMAx, uint8_t *rxBuffer, uint16_t length, DeviceCallback_Type callback);

#ifdef I2C_USE_INTERRUPT_TRANSMIT

/*!
 * @brief I2C burst write with 7/10bit addressing by interrupt handler.
 *         related to variable: g_i2cTransmitInfo
 *         related to function: I2C_MasterSlaveIntHandler
 *         I2C interrupt must be enable
 *         Stop will directly generate if master get an nack
 *
 * @param[in] I2Cx: I2C module,x can be 0.1
 * @param[in] slaveAddr: slave 7/10bit address
 * @param[in] buff: the data buffer
 * @param[in] dataLength: the length to write
 * @param[in] stopEn: enable/diable i2c send stop after lastone byte for a possible re-start
 * @return i2c hardware status
 */
uint32_t I2C_MasterTransmitInt(I2C_Type *I2Cx, uint16_t slaveAddr, uint8_t *buff, uint32_t dataLength, ACTION_Type stopEn);

/*!
 * @brief I2C burst read with 7/10bit addressing by interrupt handler.
 *         related to variable: g_i2cTransmitInfo
 *         related to function: I2C_MasterSlaveIntHandler
 *         I2C interrupt must be enable
 *
 * @param[in] I2Cx: I2C module,x can be 0.1
 * @param[in] slaveAddr: slave 7/10bit address
 * @param[in] buff: the data buffer
 * @param[in] dataLength: the length to read
 * @return i2c hardware status
 */
uint32_t I2C_MasterReceiveInt(I2C_Type *I2Cx, uint16_t slaveAddr, uint8_t *buff, uint32_t dataLength);

/*!
 * @brief I2C slave burst write/read by interrupt handler.
 *         related to variable: g_i2cTransmitInfo
 *         related to function: I2C_MasterSlaveIntHandler
 *         I2C interrupt must be enable
 *
 * @param[in] I2Cx: I2C module,x can be 0.1
 * @param[in] buff: the data buffer
 * @param[in] dataLength: the length to write/read
 * @return none
 */
void I2C_SlaveTransmitReceiveInt(I2C_Type *I2Cx, uint8_t *buff, uint32_t dataLength);

/*!
 * @brief get transmit status when use.
 *        I2C_MasterTransmitInt, I2C_MasterReceiveInt, I2C_SlaveTransmitReceiveInt
 *
 * @param[in] I2Cx: I2C module,x can be 0.1
 * @return i2c application status
 */
uint32_t I2C_GetTransmitReceiveStatus(I2C_Type *I2Cx);

/*!
 * @brief reset transmit status to I2C_TRANSMIT_STATUS_ERROR_NULL before using.
 *        I2C_MasterTransmitInt, I2C_MasterReceiveInt, I2C_SlaveTransmitReceiveInt
 *
 * @param[in] I2Cx: I2C module,x can be 0.1
 * @return none
 */
void I2C_ResetTransmitReceiveStatus(I2C_Type *I2Cx);

/*!
 * @brief get transmitted length when use I2C_MasterTransmitInt, I2C_MasterReceiveInt, I2C_SlaveTransmitReceiveInt.
 *
 * @param[in] I2Cx: I2C module,x can be 0.1
 * @return transmitted length
 */
uint32_t I2C_GetTransmittedReceivedLength(I2C_Type *I2Cx);

#endif /* I2C_USE_INTERRUPT_TRANSMIT */

#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* _AC780X_I2C_H */

/* =============================================  EOF  ============================================== */
